<?php

/** Zend_Controller_Action_Helper_Abstract */
require_once 'Zend/Controller/Action/Helper/Abstract.php';


/**
 * ACL integration
 *
 * Bet_Controller_Action_Helper_Acl provides ACL support to a
 * controller.
 *
 * @uses       Zend_Controller_Action_Helper_Abstract
 * @package    Controller
 * @subpackage Controller_Action
 */
class Bet_Controller_Action_Helper_Acl extends Zend_Controller_Action_Helper_Abstract
{
	/**
	 * @var Zend_Controller_Action
	 */
	protected $_action;

	/**
	 * @var Zend_Auth
	 */
	protected $_auth;

	/**
	 * @var Bet_Acl
	 */
	protected $_acl;

	/**
	 * @var string
	 */
	protected $_controllerName;

	/**
	 * @var string
	 */
	protected $_moduleName;

	/**
	 * @var string
	 */
	protected $_resource;

	/**
	 * Constructor
	 *
	 * Optionally set view object and options.
	 *
	 * @param  Zend_View_Interface $view
	 * @param  array $options
	 * @return void
	 */
	public function __construct(Zend_View_Interface $view = null, array $options = array())
	{
		$this->_auth = Zend_Auth::getInstance();
		$this->_acl = $options['acl'];
	}

	/**
	 * Hook into action controller initialization
	 *
	 * @return void
	 */
	public function init()
	{
		$this->_action = $this->getActionController();

		// add resource for this controller
		$controller = $this->_action->getRequest()->getControllerName();
		$module = $this->_action->getRequest()->getModuleName();
		$this->_controllerName = $controller;
		$this->_moduleName = $module;

		$resource = $module . Bet_Constants::RESOURCE_SEPARATOR . $controller;
		$this->_resource = $resource;
		if(!$this->_acl->has($resource)) {
			$this->_acl->add(new Zend_Acl_Resource($resource));
		}

	}

	/**
	 * Hook into action controller preDispatch() workflow
	 *
	 * @return void
	 */
	public function preDispatch()
	{
		if ($this->_auth->hasIdentity()) {
			$identity = $this->_auth->getIdentity();
			if(is_object($identity)) {
				$roles = $identity->roles;
			}
		}

		if (!isset($roles) || count($roles) == 0) {
			$roles = array('guest');
		}

		$request = $this->_action->getRequest();
		$action = $request->getActionName();

		$resource = $this->_resource;
		$privilege = $action;

		if (!$this->_acl->has($resource)) {
			$resource = null;
		}

		$isAllowed = false;
		foreach ($roles as $role) {
			if ($this->_acl->isAllowed($role, $resource, $privilege)) {
				$isAllowed = true;
				break;
			}
		}

		if (!$isAllowed) {
			if (!$this->_auth->hasIdentity()) {
				$noPermsAction = $this->_acl->getNoAuthAction();
			} else {
				$noPermsAction = $this->_acl->getNoAclAction();
			}

			$request->setModuleName($this->_moduleName);
			$request->setControllerName($noPermsAction['controller']);
			$request->setActionName($noPermsAction['action']);
			$request->setDispatched(false);
		}
	}

	/**
	 * Proxy to the underlying Zend_Acl's allow()
	 *
	 * We use the controller's name as the resource and the
	 * action name(s) as the privilege(s)
	 *
	 * @param  Zend_Acl_Role_Interface|string|array     $roles
	 * @param  string|array                             $actions
	 * @uses   Zend_Acl::setRule()
	 * @return Places_Controller_Action_Helper_Acl Provides a fluent interface
	 */
	public function allow($roles = null, $actions = null)
	{
		$resource = $this->_resource;
		$this->_acl->allow($roles, $resource, $actions);
		return $this;
	}

	/**
	 * Proxy to the underlying Zend_Acl's deny()
	 *
	 * We use the controller's name as the resource and the
	 * action name(s) as the privilege(s)
	 *
	 * @param  Zend_Acl_Role_Interface|string|array     $roles
	 * @param  string|array                             $actions
	 * @uses   Zend_Acl::setRule()
	 * @return Places_Controller_Action_Helper_Acl Provides a fluent interface
	 */
	public function deny($roles = null, $actions = null)
	{
		$resource = $this->_resource;
		$this->_acl->deny($roles, $resource, $actions);
		return $this;
	}

}
